#include "qyklabel.h"
#include <QPainter>
#include "YK16GrayImage.h"

using namespace std;

qyklabel::qyklabel(QWidget *parent)
	: QLabel(parent)
{
	m_pYK16Image = NULL;	
	m_bDrawPoints = true;
	m_iMouseWheelDelta = 0;
	m_bFocusIn = false;
	m_pYK16ImageROI = NULL;
}

qyklabel::~qyklabel()
{
}

void qyklabel::mouseMoveEvent( QMouseEvent *ev )
{
	if (m_pYK16Image == NULL)
		return;
	
	this->x	= ev->x();
	this->y = ev->y();
	emit Mouse_Move();
}

void qyklabel::mousePressEvent( QMouseEvent *ev )
{
	if (m_pYK16Image == NULL)
		return;
	this->x	= ev->x();
	this->y = ev->y();

	if (ev->button() == Qt::LeftButton)
	{	 
		emit Mouse_Pressed_Left();
	}
	if (ev->button() == Qt::RightButton)
	{	  
		emit Mouse_Pressed_Right();
	}
}

void qyklabel::mouseReleaseEvent( QMouseEvent *ev )
{
//  if (m_pYK16Image == NULL)
	//return;

  //cout << "Mouse Released from qlabel" << endl;//it worked

  if (ev->button() == Qt::LeftButton)
  {	
	emit Mouse_Released_Left();
  }
  if (ev->button() == Qt::RightButton)
  {
	emit Mouse_Released_Right();  
  }
}


void qyklabel::wheelEvent( QWheelEvent * event )
{
  if (m_pYK16Image == NULL)
	return;

  m_iMouseWheelDelta = (int)(event->delta()/100.0);
  emit Mouse_Wheel();
}

void qyklabel::mouseDoubleClickEvent(QMouseEvent *ev)
{
	this->x = ev->x();
	this->y = ev->y();
	//emit Mouse_DoubleClicked();
}

void qyklabel::enterEvent (QEvent *)
{
  if (m_pYK16Image == NULL)
	return;

  m_bFocusIn = true;

  emit FocusIn();
}

void qyklabel::leaveEvent( QEvent * )
{  
	if (m_pYK16Image == NULL)
		return;	


	m_bFocusIn = false;

	emit FocusOut();
}

//void focusInEvent ( QFocusEvent * ev );
//void focusOutEvent ( QFocusEvent * ev );
//
//void qyklabel::focusInEvent( QFocusEvent * )
//{
//  cout <<"focus in" << endl;
//  emit FocusIn();  
//}
//
//void qyklabel::focusOutEvent( QFocusEvent * )
//{
//  cout <<"focus out" << endl;
//  emit FocusOut();  
//}

void qyklabel::paintEvent( QPaintEvent * )
{    
	QPainter painter(this);

	painter.setPen( QPen(Qt::black, 2));
	QRect TargetRt = this->rect();	
	painter.drawRect(TargetRt);

	if (m_pYK16Image == NULL)
		return;

	if (m_pYK16Image->m_iWidth < 1 || m_pYK16Image->m_iHeight<1)
		return;

	double VH_ratio = 0.0; //if horizontal is longer than vertical        

	bool bHorLonger = false;

	double physHor = 0.0;
	double physVer = 0.0;

	int labelNewFixedWidth = 0;
	int labelNewFixedHeight = 0;


	if (m_pYK16Image->m_fSpacingX*m_pYK16Image->m_fSpacingY == 0)
	{
		physHor = (double)m_pYK16Image->m_iWidth;
		physVer = (double)m_pYK16Image->m_iHeight;
	}
	else
	{
		physHor = m_pYK16Image->m_iWidth * m_pYK16Image->m_fSpacingX;
		physVer = m_pYK16Image->m_iHeight* m_pYK16Image->m_fSpacingY;
	}

	VH_ratio = physVer / physHor;

	if (physHor > physVer)
	{
		bHorLonger = true;
		int newFixedHeight = qRound(this->width() * VH_ratio);
		this->setFixedHeight(newFixedHeight);
	}
	else
	{
		bHorLonger = false;
		int newFixedWidth = qRound(this->height() / VH_ratio);
		this->setFixedWidth(newFixedWidth);
	}


	//Calculate ver / hor ratio.
	/*VH_ratio = m_pYK16Image->m_iHeight / (double) m_pYK16Image->m_iWidth;
	int newFixedHeight = qRound(this->width() * VH_ratio);
	this->setFixedHeight(newFixedHeight);*/

	QRect rtDspROI;
	QPoint dspPtLeftTop, dspPtRightBottom;
	
	

	if (m_pYK16Image != NULL)
	{		
		painter.drawImage(TargetRt, m_pYK16Image->m_QImage); //it Works!YKTEMP	

		if (m_pYK16ImageROI != NULL && m_pYK16Image->m_bDrawROI)
		{
			//calculate ROI position in qlabel
			if (!m_pYK16ImageROI->m_QImage.isNull())
			{
				dspPtLeftTop = Data2View(m_pYK16Image->m_rtROI.topLeft(), this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);
				dspPtRightBottom = Data2View(m_pYK16Image->m_rtROI.bottomRight(), this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);
				rtDspROI = QRect(dspPtLeftTop, dspPtRightBottom);

				painter.drawImage(rtDspROI, m_pYK16ImageROI->m_QImage); //it Works!						
			}

			//if (!m_pYK16ImageROI->m_QImage.isNull() && m_rtDspROIRect.width() > 5 && m_rtDspROIRect.height() > 5)
			//{
			//	painter.drawImage(m_rtDspROIRect, m_pYK16ImageROI->m_QImage); //it Works!						
			//}
				
		}
	}	

	
	if (m_pCurSnake != NULL)
	{
		////int cnt = m_pCurSnake->m_log.Sm;
		//int cnt = m_pCurSnake->m_log.Sm;
		//int arrSize = cnt - m_pCurSnake->m_vExcludedIdx.size();


		//if (cnt > 0)
		//{
		//	painter.setPen(QPen(Qt::green, 3));
		//	QPoint* viewSnakePt = new QPoint[arrSize];
		//	int j = 0;

		//	for (int i = 0; i <cnt; i++)
		//	{
		//		vector<int>::iterator it;

		//		bool bExistInList = false;

		//		for (it = m_pCurSnake->m_vExcludedIdx.begin(); it != m_pCurSnake->m_vExcludedIdx.end(); it++)
		//		{
		//			if (i == (*it))
		//			{
		//				bExistInList = true;
		//				break;
		//			}
		//		}

		//		if (!bExistInList)
		//		{
		//			QPointF ptInROI = QPointF(m_pCurSnake->m_Seed[i].point.x, m_pCurSnake->m_Seed[i].point.y);
		//			QPointF ptInWholeImg = QPointF(ptInROI.x() + m_pCurSnake->m_ptOffset.x(), ptInROI.y() + m_pCurSnake->m_ptOffset.y());
		//			viewSnakePt[j] = Data2View(ptInWholeImg, this->width(), this->height(), m_pYK16Image->m_iWidth,
		//				m_pYK16Image->m_iHeight);
		//			j++;
		//		}
		//	}
		//	painter.drawPoints(viewSnakePt, arrSize);
		//	delete[] viewSnakePt;
		//}
	}

	/*int top = m_rtDspROIRect.top();
	int left = m_rtDspROIRect.left();
	int right = m_rtDspROIRect.right();
	int bottom = m_rtDspROIRect.bottom();*/	
	if (m_bDrawPoints)// old method. for futher project, use below function
	{
		painter.setPen(QPen(Qt::red, 2));
		vector<QPoint>::iterator it;
		for (it = m_vPt.begin(); it != m_vPt.end(); it++)
		{
			painter.drawPoint((*it).x(), (*it).y());
		}
	}

	if (m_pYK16Image->m_bDrawMarkersRef)// Draw reference points
	{	
		int cntMarkerRef = m_pYK16Image->m_vMarkerRef.size();		
		
		QPoint tmpDataPt;		
		QPoint tmpViewPt;

		for (int i = 0; i < cntMarkerRef; i++)
		{	
			if (i == 0)
				painter.setPen(QPen(Qt::green, 4));
			else if (i == 1)
				painter.setPen(QPen(Qt::yellow, 4));
			else if (i == 2)
				painter.setPen(QPen(Qt::blue, 4));
			else
				painter.setPen(QPen(Qt::white, 4));

			tmpDataPt = m_pYK16Image->m_vMarkerRef.at(i);
			tmpViewPt = Data2View(tmpDataPt, this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);
			painter.drawPoint(tmpViewPt);
		}
	}
	
	if (m_pYK16Image->m_bDrawMarkers)
	{
		//painter.setPen(QPen(Qt::red, 1));
		vector<QPoint>::iterator it;

		QRect rtDraw;
		int MarkerROI_width = 20; //data pixels
		int MarkerROI_height = 20; //data pixels

		//int iMaxNumMarker = 3;
		int cnt = 0;

		//w/o edit, default value is -1 
		if (m_pYK16Image->m_iNumOfDispMarker > 0)
		{
			for (it = m_pYK16Image->m_vMarker.begin(); it != m_pYK16Image->m_vMarker.end(); it++)
			{
				if (cnt == 0)
					painter.setPen(QPen(Qt::green, 1));
				else if (cnt == 1)
					painter.setPen(QPen(Qt::yellow, 1));
				else if (cnt == 2)
					painter.setPen(QPen(Qt::blue, 1));
				else
					painter.setPen(QPen(Qt::white, 1));
				
				rtDraw.setTopLeft(Data2View(QPoint((*it).x() - MarkerROI_width / 2.0, (*it).y() - MarkerROI_height / 2.0), this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight));
				rtDraw.setBottomRight(Data2View(QPoint((*it).x() + MarkerROI_width / 2.0, (*it).y() + MarkerROI_height / 2.0), this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight));
				painter.drawRect(rtDraw);
				cnt++;

				if (cnt >= m_pYK16Image->m_iNumOfDispMarker)
					break;
			}
		}
	}

        if (m_pYK16Image->m_vvContourROI.size() > 1)
        {
            int cntROI = m_pYK16Image->m_vvContourROI.size();

            for (int i = 0; i < cntROI; i++)
            {
                CContourROI* pContourROI = m_pYK16Image->m_vvContourROI.at(i);    
                //QColor color = QColor()

               // Qt::red
                painter.setPen(QPen(QColor(pContourROI->_rgb), pContourROI->_thick));

                QPoint tmpDataPt;
                QPoint tmpViewPt;

                int contourSize = pContourROI->_vDataPt.size();

                QPoint prevViewPt;
                QPoint firstViewPt;

                vector<QPoint>::iterator it;

                for (it = pContourROI->_vDataPt.begin(); it != pContourROI->_vDataPt.end(); it++)
                {
                    tmpDataPt = (*it);
                    tmpViewPt = Data2View(tmpDataPt, this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);

                    if (it == pContourROI->_vDataPt.begin())
                    {
                        prevViewPt = tmpViewPt;
                        firstViewPt = tmpViewPt;
                        continue;
                    }
                    //painter.drawPoint(tmpViewPt);
                    painter.drawLine(prevViewPt, tmpViewPt);
                    prevViewPt = tmpViewPt;

                    if (it == pContourROI->_vDataPt.end() - 1) //if last point, one more line draw
                    {
                        painter.drawLine(tmpViewPt, firstViewPt);
                    }
                }
            }
        }

        if (m_pYK16Image->m_bDrawROI)//draw ROI BOX
        {
            painter.setPen(QPen(Qt::red, 2));
            QRect rtDraw;
            rtDraw.setTopLeft(Data2View(QPoint(m_pYK16Image->m_rtROI.left(), m_pYK16Image->m_rtROI.top()), this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight));
            rtDraw.setBottomRight(Data2View(QPoint(m_pYK16Image->m_rtROI.right(), m_pYK16Image->m_rtROI.bottom()), this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight));

            painter.drawRect(rtDraw);
        }
	
	//if x, y >0 
	if (m_pYK16Image->m_bDrawProfileX)
	{
		QPoint crntViewPt = Data2View(m_pYK16Image->m_ptProfileProbe, this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);
		painter.setPen( QPen(Qt::red, 1, Qt::DotLine));		
		painter.drawLine(0, crntViewPt.y(), this->width()-1, crntViewPt.y());
		
	}
	if (m_pYK16Image->m_bDrawProfileY)
	{
		QPoint crntViewPt = Data2View(m_pYK16Image->m_ptProfileProbe, this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);
		painter.setPen( QPen(Qt::red, 1, Qt::DotLine));
		painter.drawLine(crntViewPt.x(), 0 ,crntViewPt.x(), this->height()-1);
	}

	if (m_pYK16Image->m_bDrawFOVCircle)
	{
		painter.setPen( QPen(Qt::yellow, 1, Qt::SolidLine));
		QPoint crntCenterPt = Data2View(m_pYK16Image->m_ptFOVCenter, this->width(), this->height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);		
		int crntRadius = (int)(m_pYK16Image->m_iFOVRadius / (double)m_pYK16Image->m_iWidth * this->width());
		painter.drawEllipse(crntCenterPt,crntRadius, crntRadius);
	}

	if (m_pYK16Image->m_bDrawTableLine)
	{
		painter.setPen( QPen(Qt::yellow, 1, Qt::SolidLine));
		int crntTablePosY = (int)(m_pYK16Image->m_iTableTopPos / (double)m_pYK16Image->m_iHeight * this->height());
		//int crntRadius = (int)(m_pYK16Image->m_iFOVRadius / (double)m_pYK16Image->m_iWidth * this->width());
		painter.drawLine(0, crntTablePosY ,this->width()-1, crntTablePosY);
		//painter.drawEllipse(crntCenterPt,crntRadius, crntRadius);
	}

	if (m_pYK16Image->m_bDrawCrosshair) //objects should be addressed one by one
	{
	  painter.setPen( QPen(Qt::yellow, 1, Qt::SolidLine));
	  //QPoint crosshair;

	  int dispCrossX = (int)(m_pYK16Image->m_ptCrosshair.x() / (double)m_pYK16Image->m_iWidth * this->width());
	  int dispCrossY = (int)(m_pYK16Image->m_ptCrosshair.y() / (double)m_pYK16Image->m_iHeight * this->height());

	  QPoint ptDispCrosshair = GetViewPtFromDataPt(m_pYK16Image->m_ptCrosshair.x(), m_pYK16Image->m_ptCrosshair.y());
		//crosshair.setX(crossX);
		//crosshair.setY(crossY);

		//int crntRadius = (int)(m_pYK16Image->m_iFOVRadius / (double)m_pYK16Image->m_iWidth * this->width());
	  painter.drawLine(0, ptDispCrosshair.y() ,this->width()-1, ptDispCrosshair.y());
	  painter.drawLine(ptDispCrosshair.x(), 0, ptDispCrosshair.x(), this->height()-1);
	}
}

void qyklabel::SetBaseImage( YK16GrayImage* pYKImage )
{
	if (pYKImage->m_pData != NULL && !pYKImage->m_QImage.isNull()) //YKTEMP
		m_pYK16Image = pYKImage;
}

void qyklabel::ConvertAndCopyPoints(vector<QPoint>& vSrcPoint, int iDataWidth, int iDataHeight)
{
	m_vPt.clear();	

	int dspWidth = this->width();
	int dspHeight = this->height();


	vector<QPoint>::iterator it;

	for (it = vSrcPoint.begin() ; it != vSrcPoint.end() ; it++)
	{
		QPoint tmpDspPt = Data2View((*it),dspWidth, dspHeight, iDataWidth, iDataHeight);
		m_vPt.push_back(tmpDspPt);
	}
}


QPoint qyklabel::View2Data(QPoint viewPt, int viewWidth, int viewHeight, int dataWidth, int dataHeight)
{
	double fZoomX = viewWidth / (double)dataWidth;
	double fZoomY = viewHeight / (double)dataHeight;

	QPoint dataPt;
	dataPt.setX(qRound(viewPt.x() / fZoomX));
	dataPt.setY(qRound(viewPt.y() / fZoomY));

	return dataPt;
}

QPoint qyklabel::Data2View(QPoint dataPt, int viewWidth, int viewHeight, int dataWidth, int dataHeight)
{
	double fZoomX = viewWidth / (double)dataWidth;
	double fZoomY = viewHeight / (double)dataHeight;

	QPoint viewPt;
	viewPt.setX(qRound(dataPt.x() * fZoomX));
	viewPt.setY(qRound(dataPt.y() * fZoomY));

	return viewPt;
}

void qyklabel::SetDrawPointToggle(bool bToggle )
{
	if (bToggle)
		m_bDrawPoints = true;
	else
		m_bDrawPoints = false;


	update();
}

QPoint qyklabel::GetDataPtFromMousePos()
{
  if (m_pYK16Image == NULL)
	return QPoint(0,0);

  
  if (m_pYK16Image->m_fZoom == 1.0 && m_pYK16Image->m_iOffsetX == 0 && m_pYK16Image->m_iOffsetY == 0)
	return View2Data(QPoint(this->x, this->y), width(), height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);  
  else
	return View2DataExt(QPoint(this->x, this->y), width(), height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight, QPoint(m_pYK16Image->m_iOffsetX,m_pYK16Image->m_iOffsetY),m_pYK16Image->m_fZoom );

}

QPoint qyklabel::GetDataPtFromViewPt(int viewPtX, int viewPtY)
{
  if (m_pYK16Image == NULL)
	return QPoint(0,0);  

  if (m_pYK16Image->m_fZoom == 1.0 && m_pYK16Image->m_iOffsetX == 0 && m_pYK16Image->m_iOffsetY == 0)
	return View2Data(QPoint(viewPtX, viewPtY), width(), height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);  
  else
	return View2DataExt(QPoint(viewPtX, viewPtY), width(), height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight, QPoint(m_pYK16Image->m_iOffsetX,m_pYK16Image->m_iOffsetY),m_pYK16Image->m_fZoom ); 
}

QPoint qyklabel::GetViewPtFromDataPt(int dataPtX, int dataPtY)
{
  if (m_pYK16Image == NULL)
	return QPoint(0,0);  

  if (m_pYK16Image->m_fZoom == 1.0 && m_pYK16Image->m_iOffsetX == 0 && m_pYK16Image->m_iOffsetY == 0)
	return Data2View(QPoint(dataPtX, dataPtY), width(), height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight);
  else
	return Data2ViewExt(QPoint(dataPtX, dataPtY), width(), height(), m_pYK16Image->m_iWidth, m_pYK16Image->m_iHeight, QPoint(m_pYK16Image->m_iOffsetX,m_pYK16Image->m_iOffsetY),m_pYK16Image->m_fZoom ); 
}



QPoint qyklabel::View2DataExt(QPoint viewPt, int viewWidth, int viewHeight, int dataWidth, int dataHeight, QPoint ptDataOffset, double fUserZoom)
{
  // double fZoomX = viewWidth / (double)dataWidth * fUserZoom; // < 1 
  //double fZoomY = viewHeight / (double)dataHeight * fUserZoom;  

  
  //  dataPt.setX(qRound(viewPt.x() * fZoomX  + ptDataOffset.x()));
  //  dataPt.setY(qRound(viewPt.y() * fZoomY + ptDataOffset.y()));
  int newWidth = qRound(dataWidth/fUserZoom);
  int newHeight = qRound(dataHeight/fUserZoom);

  int dataCenterX = ptDataOffset.x() + qRound(dataWidth/2.0);
  int dataCenterY = ptDataOffset.y() + qRound(dataHeight/2.0);

  int dataLeftTopX = dataCenterX - qRound(newWidth/2.0);//data position
  int dataLeftTopY = dataCenterY - qRound(newHeight/2.0);	//data position


  QPoint dataPt;
  dataPt.setX(qRound(viewPt.x()*newWidth/(double)viewWidth + dataLeftTopX));
  dataPt.setY(qRound(viewPt.y()*newHeight/(double)viewHeight + dataLeftTopY)); 

  return dataPt;
}

QPoint qyklabel::Data2ViewExt( QPoint dataPt, int viewWidth, int viewHeight, int dataWidth, int dataHeight, QPoint ptDataOffset, double fUserZoom )
{
  int newWidth = qRound(dataWidth/fUserZoom);
  int newHeight = qRound(dataHeight/fUserZoom);

  int dataCenterX = ptDataOffset.x() + qRound(dataWidth/2.0);
  int dataCenterY = ptDataOffset.y() + qRound(dataHeight/2.0);

  int dataLeftTopX = dataCenterX - qRound(newWidth/2.0);//data position
  int dataLeftTopY = dataCenterY - qRound(newHeight/2.0);	//data position


  QPoint viewPt;
  viewPt.setX(qRound((dataPt.x() - dataLeftTopX) * viewWidth/(double)newWidth));
  viewPt.setY(qRound((dataPt.y() - dataLeftTopY) * viewHeight/(double)newHeight));  

  return viewPt;
}

void qyklabel::SetROIImage(YK16GrayImage* pYKImage)
{
	m_pYK16ImageROI = pYKImage;
}


//void qyklabel::setDspROIRect(QRect& dspRt)
//{
//	m_rtDspROIRect = dspRt;
//}

//void qyklabel::setROIDspSwitch(bool bChecked)
//{
//	m_bROIDisp = bChecked;
//}

void qyklabel::SetSnake(CSnake* pCurSnake)
{
	if (pCurSnake == NULL)
		return;

	m_pCurSnake = pCurSnake;
}

void qyklabel::ReDraw()
{
	update();
}

void qyklabel::SetLineDirection(bool bDirection)
{
	m_bDirection = bDirection;
	update();
}
